home *** CD-ROM | disk | FTP | other *** search
- /*
- File: Menu.cp
-
- Contains: A MenuBar class deliberately designed to resemble
- ODMenuBar from OpenDoc™
-
- Written by: Dave Falkenburg
-
- Copyright: © 1994-95 by Dave Falkenburg, all rights reserved.
-
- Change History (most recent first):
-
- <3> 1/24/95 DRF Finished implementing resource-based command registration (CMNU
- support).
- <2> 1/20/95 DRF Implemented GetNewMenuBar. GetMenuFromCMNU is next.
- <1> 1/3/95 DRF First checked in.
- */
-
- #include "MenuBar.h"
- #include <Resources.h>
- #include <Errors.h>
-
- inline UInt32 BuildKey(UInt16 hiword, UInt16 loword)
- {
- return (((UInt32) hiword << 16) | loword);
- }
-
- TMenuItemTable::CompareResult
- TMenuItemTable::Compare(ArrayElementPtr element1,ArrayElementPtr element2)
- {
- UInt32 key1 = BuildKey(((MenuMapping *) element1)->fMenu, ((MenuMapping *) element1)->fItem);
- UInt32 key2 = BuildKey(((MenuMapping *) element2)->fMenu, ((MenuMapping *) element2)->fItem);
-
- return (key2 - key1);
- }
-
-
- TMenuCommandTable::CompareResult
- TMenuCommandTable::Compare(ArrayElementPtr element1,ArrayElementPtr element2)
- {
- return (((MenuMapping *) element2)->fCommand - ((MenuMapping *) element1)->fCommand);
- }
-
-
- OSErr
- TMenuBar::GetNewMenuBar(short whichMBAR)
- {
- MenuBarResource ** mbarResource = (MenuBarResource **) GetResource('MBAR',whichMBAR);
-
- if (mbarResource)
- {
- UInt16 menuCount = (**mbarResource).numberOfMenus;
- UInt16 menuIndex = 0;
-
- HLock((Handle) mbarResource);
-
- while (menuCount--)
- {
- SInt16 whichMenu = (**mbarResource).menuIDList[menuIndex];
- MenuRef theMenu;
-
- // try to make the MenuRef from a 'CMNU' which allows us to
- // automatically register any commands we find in the resource.
-
- theMenu = this->GetMenuFromCMNU(whichMenu);
- if (theMenu == NULL)
- {
- // no 'CMNU' was found, so go ahead and use a 'MENU'
- // resource, knowing that we must register commands
- // manually.
-
- theMenu = GetMenu(whichMenu);
- }
-
- // Add the menu to the end of the menubar
- if (theMenu)
- InsertMenu(theMenu,0);
- else
- return resNotFound;
-
- menuIndex++;
- }
-
- // force a redraw of the menubar at the next possible opportunity
-
- InvalMenuBar();
-
- HUnlock((Handle) mbarResource);
- ReleaseResource((Handle) mbarResource);
- }
- else
- return resNotFound;
-
- return noErr;
- }
-
-
- // Define some functions to help us walk through CMNU resources
- // (this should make the code a bit more readable)
-
- static MenuCommandID *FindMenuCommandPtrFromCMNUItem(CMNUItemData *currentItem);
- static CMNUItemData *FindNextCMNUItem(CMNUItemData *currentItem);
-
-
- static MenuCommandID *
- FindMenuCommandPtrFromCMNUItem(CMNUItemData *currentItem)
- {
- Byte * p = (Byte *) currentItem;
-
- if ((*p) == NULL) // we’re at the end of the CMNU!
- return NULL;
-
- p += (*p) + 1 // itemString[0], a.k.a. the length
- + sizeof(Byte) // itemIcon
- + sizeof(Byte) // itemCmd
- + sizeof(Byte) // itemMark
- + sizeof(Style); // itemStyle
- p = (Byte *) ((((long) p) + 1) & ~1); // align up to the next even boundary
-
- return (MenuCommandID *) p;
- }
-
-
- static CMNUItemData *
- FindNextCMNUItem(CMNUItemData *currentItem)
- {
- return (CMNUItemData *)
- (FindMenuCommandPtrFromCMNUItem(currentItem) + 1);
- }
-
-
- MenuRef
- TMenuBar::GetMenuFromCMNU(short whichMenu)
- {
- CMNUResource ** theCMNU = (CMNUResource **) GetResource('CMNU',whichMenu);
- MenuRef newMenuRef = NULL;
-
- if (theCMNU)
- {
- HLock((Handle) theCMNU);
-
- MenuID theMenuID = (**theCMNU).menuID;
- MenuItemID itemNum = 1;
- MenuCommandID theCommand;
-
- // Make a new MenuRef from the CMNU data, eh?
- newMenuRef = NewMenu(theMenuID,(**theCMNU).menuTitle);
-
- // MENU & CMNU resources suck, don’t they?
- Byte * p = (Byte *) (**theCMNU).menuTitle;
-
- // Don’t forget to skip past string and length byte
- p += *p + 1;
-
- CMNUItemData * theItemData = (CMNUItemData *) p;
-
- while (theItemData->itemString[0]) // do we have any menu items
- {
- p = (Byte *) theItemData;
- p += *p +1;
-
- // use the item data to build a new menuitem
- AppendMenu(newMenuRef,theItemData->itemString);
- SetItemIcon(newMenuRef,itemNum,*p++);
- SetItemCmd(newMenuRef,itemNum,*p++);
- SetItemMark(newMenuRef,itemNum,*p++);
- SetItemStyle(newMenuRef,itemNum,*p++);
-
- // deal with any disabled items
- if (!((**theCMNU).enableFlags & (1 << itemNum)))
- DisableItem(newMenuRef,itemNum);
-
- // align up to the next even boundary
- p = (Byte *) ((((long) p) + 1) & ~1);
-
- // register the menu command, if any
- theCommand = *((MenuCommandID *) p);
- if (theCommand)
- this->RegisterCommand(theCommand,theMenuID,itemNum);
-
- theItemData = FindNextCMNUItem(theItemData);
- itemNum++;
- }
-
- ReleaseResource((Handle) theCMNU);
- }
-
- return newMenuRef;
- }
-
-
- // menu command mapping functions
-
- // find the menu command in the array, given the menu and item
-
- MenuCommandID
- TMenuBar::GetCommand(MenuID menu, MenuItemID item)
- {
- MenuMapping key = {menu,item,kNoMenuCommandID};
- MenuMapping * foundMapping;
-
- foundMapping = (MenuMapping *) fMenuItemTable.Find(&key);
-
- if (foundMapping)
- return foundMapping->fCommand;
-
- return kNoMenuCommandID;
- }
-
-
- // find the menu and item in the array, given the menu command
-
- void
- TMenuBar::GetMenuAndItem(MenuCommandID commandNum, MenuID * returnedMenu, MenuItemID * returnedItem)
- {
- MenuMapping key = {kNoMenuID,kNoMenuItemID,commandNum};
- MenuMapping * foundMapping;
-
- foundMapping = (MenuMapping *) fCommandTable.Find(&key);
-
- if (foundMapping)
- {
- *returnedMenu = foundMapping->fMenu;
- *returnedItem = foundMapping->fItem;
- }
- else
- {
- *returnedMenu = kNoMenuID;
- *returnedItem = kNoMenuItemID;
- }
- }
-
-
- OSErr
- TMenuBar::RegisterCommand(MenuCommandID commandNum, MenuID menu, MenuItemID item)
- {
- MenuMapping * aMapping = new MenuMapping;
-
- if (aMapping == NULL)
- return MemError();
-
- aMapping->fMenu = menu;
- aMapping->fItem = item;
- aMapping->fCommand = commandNum;
-
- fCommandTable.Add(aMapping);
- fMenuItemTable.Add(aMapping);
-
- return noErr;
- }
-
-
- OSErr
- TMenuBar::UnregisterCommand(MenuCommandID commandNum)
- {
- MenuMapping key = {kNoMenuID,kNoMenuItemID,commandNum};
-
- return noErr;
- }
-
-
- // menu enable/disable routines for menu items
-
- MenuHandle
- TMenuBar::GetMenuHandleAndItemFromCommand(MenuCommandID commandNum, MenuID *menu, MenuItemID *item)
- {
- this->GetMenuAndItem(commandNum,menu,item);
- if (*menu != kNoMenuID)
- return GetMenuHandle(*menu);
- else
- return NULL;
- }
-
-
- void
- TMenuBar::EnableCommand(MenuCommandID commandNum, Boolean enable)
- {
- MenuHandle menuHandle;
- MenuID menu;
- MenuItemID item;
-
- menuHandle = this->GetMenuHandleAndItemFromCommand(commandNum,&menu,&item);
- if (menuHandle)
- {
- if (enable)
- EnableItem(menuHandle,item);
- else
- DisableItem(menuHandle,item);
- }
- }
-
-
- void
- TMenuBar::EnableAndCheckCommand(MenuCommandID commandNum, Boolean enable, Boolean check)
- {
- MenuHandle menuHandle;
- MenuID menu;
- MenuItemID item;
-
- menuHandle = this->GetMenuHandleAndItemFromCommand(commandNum,&menu,&item);
- if (menuHandle)
- {
- CheckItem(menuHandle,item,check);
-
- if (enable)
- EnableItem(menuHandle,item);
- else
- DisableItem(menuHandle,item);
- }
- }
-
-
- void
- TMenuBar::GetItemString(MenuCommandID commandNum,StringPtr itemString)
- {
- MenuHandle menuHandle;
- MenuID menu;
- MenuItemID item;
-
- menuHandle = this->GetMenuHandleAndItemFromCommand(commandNum,&menu,&item);
- if (menuHandle)
- GetMenuItemText(menuHandle,item,itemString);
- }
-
-
- void
- TMenuBar::SetItemString(MenuCommandID commandNum,StringPtr itemString)
- {
- MenuHandle menuHandle;
- MenuID menu;
- MenuItemID item;
-
- menuHandle = this->GetMenuHandleAndItemFromCommand(commandNum,&menu,&item);
- if (menuHandle)
- SetMenuItemText(menuHandle,item,itemString);
- }
-
-
- Boolean TMenuBar::fgMenuBarHidden = false;
-
-
- /* static */ void
- TMenuBar::HideMenuBar()
- {
- }
-
-
- /* static */ void
- TMenuBar::ShowMenuBar()
- {
- }
-
-
- /* static */ void
- TMenuBar::EnterModalState()
- {
- }
-
-
- /* static */ void
- TMenuBar::ExitModalState()
- {
- }
-